<!DOCTYPE html>
<html>

<head>
    <meta charset="UTF-8">
    <meta content="width=device-width, initial-scale=1.0" name="viewport">
    <!-- 空referrer才能加载b站图片 -->
    <meta name="referrer" content="no-referrer">
    <title>心愿目标示例</title>
    <style>
        body {
            margin: 0;
            padding: 0;
            overflow: hidden;
        }

        #container {
            width: 100%;
            display: flex;
            flex-flow: column nowrap;
            gap: 10px;
            white-space: nowrap;
        }

        #container.horizontal {
            min-width: fit-content;
            flex-flow: row nowrap;
        }

        #container.horizontal>* {
            min-width: 200px;
            flex: 1;
        }

        .header {
            display: flex;
            flex-flow: row nowrap;
            justify-content: space-between;
            align-items: center;
        }

        .gift {
            display: flex;
            align-items: center;
        }

        .gift .img {
            width: 54px;
            height: 54px;
        }

        .gift .name,
        .percent {
            font-size: large;
            font-weight: bold;
        }

        .rail {
            height: 30px;
            border: 2px solid skyblue;
            border-radius: 10px;
            overflow: hidden;
        }

        .progress {
            height: 100%;
            width: 0;
            background-color: orange;
            transition: width .5s;
        }
    </style>
    <script>
        const query = new URLSearchParams(location.search)
        // 是否处于配置环境
        const isSetup = query.get('env') === '1'
        const settings = {
            config: [],
            direction: "vertical",
        }

        // 防抖避免写入过快
        function debounce(func, timeout = 300) {
            let timer;
            return (...args) => {
                clearTimeout(timer);
                timer = setTimeout(() => { func.apply(this, args); }, timeout);
            };
        }

        function drawTextShadow(strokeSize, strokeColor, blur = 0) {
            const shadow = []
            for (let angle = 0; angle < 2 * Math.PI; angle += 1 / strokeSize) {
                shadow.push(`${Math.cos(angle) * strokeSize}px ${Math.sin(angle) * strokeSize}px ${blur}px ${strokeColor}`);
            }
            return shadow.join(',')
        }

        function rand(min, max) {
            return Math.floor(Math.random() * (max - min) + min)
        }
    </script>
</head>

<body>
    <template id="giftItemTemplate">
        <div class="item">
            <div class="header">
                <div class="gift">
                    <img class="img"></span>
                    <span class="name"></span>
                </div>
                <div class="percent"></div>
            </div>
            <div class="rail">
                <div class="progress"></div>
            </div>
        </div>
    </template>
    <div id="container">

    </div>
    <script>
        let options = []

        const container = document.getElementById('container')
        const template = document.getElementById('giftItemTemplate').content

        function updateSize() {
            const { width, height } = container.getBoundingClientRect()
            parent.postMessage({
                fun: 'attr',
                args: settings.direction === 'horizontal' ? {
                    w: Math.ceil(width),
                } : {
                    h: Math.ceil(height),
                }
            }, '*')
        }

        new ResizeObserver(updateSize).observe(container)

        function updateStyles(newValue) {
            const { documentElement } = document
            documentElement.style.setProperty('color', newValue.fontColor)
            documentElement.style.setProperty('text-shadow', drawTextShadow(2, newValue.strokeColor))
            container.classList[newValue.direction === 'horizontal' ? 'add' : 'remove']('horizontal')
        }

        function updateGift(newValue) {
            const changed = options.length !== newValue.config.length || newValue.config.some((v, idx) => {
                return v.gift.id !== options[idx].gift.id
            })
            console.log('礼物变化', changed)
            if (changed) {
                options = newValue.config.map(v => ({
                    ...v,
                    received: 0,
                }))
                render(true)
            } else {
                for (const i in options) {
                    Object.assign(options[i], newValue.config[i])
                }
                render()
            }
        }

        function render(reset) {
            if (reset) {
                container.innerHTML = ''
                for (const option of options) {
                    const item = template.cloneNode(true)
                    const giftImg = item.querySelector('.gift .img')
                    const giftName = item.querySelector('.gift .name')
                    const progress = item.querySelector('.progress')

                    giftImg.src = option.gift.webp
                    giftName.innerText = option.title

                    container.appendChild(item)
                }
            }
            const elements = Array.from(container.children)
            for (const i in elements) {
                const elem = elements[i]
                const data = options[i]
                elem.querySelector('.percent').innerText = `${data.received}/${data.amount}`
                elem.querySelector('.progress').style.setProperty('width', `${Math.min(Math.floor(data.received / data.amount * 100), 100)}%`)
            }
            if (!isSetup) save()
        }

        // 更新时存到local storage里面持久化数据
        const save = debounce(() => {
            localStorage.setItem('data', JSON.stringify(options))
        })

        function load() {
            const data = localStorage.getItem('data')
            if (data) {
                options = JSON.parse(data)
                render(true)
            }
        }

        const externalCss = document.createElement('style')
        document.head.append(externalCss)
        const handlers = {
            update: {
                user(newValue) {
                    console.log('用户信息更新了', newValue)
                },
                option(newValue) {
                    console.log('插件配置更新了', newValue)
                    const { config } = settings
                    Object.assign(settings, newValue)
                    updateStyles(newValue)
                    updateGift(newValue)
                },
                css(newValue) {
                    console.log('css更新了', newValue);
                    externalCss.innerHTML = newValue
                }
            },
            event: {
                LIVE_OPEN_PLATFORM_SEND_GIFT(e) {

                },
                LIVE_OPEN_PLATFORM_SUPER_CHAT(e) {

                }
            }
        }
        //监听事件
        window.addEventListener('message', e => {
            const { category, type, args } = e.data
            handlers[category]?.[type]?.apply(e, args)
        })
        // 订阅事件
        parent.postMessage({
            fun: 'subscribe',
            args: Object.keys(handlers.event)
        }, '*')

        // 处于配置环境时模拟送礼
        if (isSetup) {
            const timer = setInterval(() => {
                for (let option of options) {
                    option.received += rand(1, 5)
                }
                render();
            }, 2000)
        } else {
            // 恢复数据
            load()
        }

        // 可以自行发送模拟数据进行测试，再进行上传
        /***上传之前记得删除***/
        // handlers.update.option({
        //     config: [
        //         {
        //             "gift": {
        //                 "id": 32345,
        //                 "name": "人气票",
        //                 "price": 100,
        //                 "webp": "https://i0.hdslb.com/bfs/live/b26b18451c011ec46ee9e6ab0d6110a1495efc09.webp",
        //                 "img_basic": "https://s1.hdslb.com/bfs/live/18d90d7789df1786a434f3c3b23ad1a22a9cdaf7.png",
        //                 "gift_type": 0,
        //                 "coin_type": "gold",
        //                 "paid": true,
        //                 "ids": [
        //                     32345
        //                 ]
        //             },
        //             "title": "人气票",
        //             "amount": rand(100, 500)
        //         },
        //         {
        //             "gift": {
        //                 "id": 31039,
        //                 "name": "牛哇牛哇",
        //                 "price": 100,
        //                 "webp": "https://i0.hdslb.com/bfs/live/7571c8bdfcb65f9b00ab1307b2c86630f0d00859.webp",
        //                 "img_basic": "https://s1.hdslb.com/bfs/live/91ac8e35dd93a7196325f1e2052356e71d135afb.png",
        //                 "gift_type": 0,
        //                 "coin_type": "gold",
        //                 "paid": true,
        //                 "ids": [
        //                     31214,
        //                     31477,
        //                     31225,
        //                     31039
        //                 ]
        //             },
        //             "title": "牛哇牛哇",
        //             "amount": rand(100, 500)
        //         },
        //         {
        //             "gift": {
        //                 "id": 32755,
        //                 "name": "稳",
        //                 "price": 100,
        //                 "webp": "https://i0.hdslb.com/bfs/live/bad6e7d2163f1cba406dcc287bfbf2b5e1b126ad.webp",
        //                 "img_basic": "https://s1.hdslb.com/bfs/live/bac5cbb829ec697e8219af0dafdfa074e515c05c.png",
        //                 "gift_type": 0,
        //                 "coin_type": "gold",
        //                 "paid": true,
        //                 "ids": [
        //                     32755
        //                 ]
        //             },
        //             "title": "稳",
        //             "amount": rand(100, 500)
        //         }
        //     ],
        //     direction: "horizontal",
        //     fontColor: '#FFFFFF',
        //     strokeColor: '#333333',
        // })
    </script>
</body>

</html>